package org.yelongframework.spring.web.servlet.handler.exception;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.AbstractHandlerMethodExceptionResolver;
import org.yelongframework.lang.Nullable;
import org.yelongframework.spring.web.method.HandlerMethodResponseMode;
import org.yelongframework.spring.web.method.HandlerMethodResponseModeResolver;
import org.yelongframework.util.Assert;

/**
 * 根据响应结果方式来响应异常信息
 * 
 * @since 1.0.0
 */
public abstract class AbstractResponseModeHandlerMethodExceptionResolver
		extends AbstractHandlerMethodExceptionResolver {

	/** 处理器方法响应模式解析器 */
	protected final HandlerMethodResponseModeResolver handlerMethodResponseModeResolver;

	/** WEB_BODY响应异常解析 */
	protected final WebBodyResponseExceptionResolver webBodyResponseExceptionResolver;

	/** WEB_PAGE响应异常解析 */
	protected final WebPageResponseExceptionResolver webPageResponseExceptionResolver;

	// ==================================================解析处理器方法响应模式==================================================

	public AbstractResponseModeHandlerMethodExceptionResolver(
			HandlerMethodResponseModeResolver handlerMethodResponseModeResolver,
			WebBodyResponseExceptionResolver webBodyResponseExceptionResolver,
			WebPageResponseExceptionResolver webPageResponseExceptionResolver) {
		Assert.notNull(handlerMethodResponseModeResolver, "handlerMethodResponseModeResolver cannot be null");
		Assert.notNull(webBodyResponseExceptionResolver, "webBodyResponseExceptionResolver cannot be null");
		Assert.notNull(webPageResponseExceptionResolver, "webPageResponseExceptionResolver cannot be null");
		this.handlerMethodResponseModeResolver = handlerMethodResponseModeResolver;
		this.webBodyResponseExceptionResolver = webBodyResponseExceptionResolver;
		this.webPageResponseExceptionResolver = webPageResponseExceptionResolver;
	}

	// ==================================================解析处理器异常==================================================

	@Override
	protected ModelAndView doResolveHandlerMethodException(HttpServletRequest request, HttpServletResponse response,
			HandlerMethod handlerMethod, Exception ex) {
		HandlerMethodResponseMode handlerMethodResponseMode = resolveHandlerMethodResponseMode(request, response,
				handlerMethod, ex);
		if (null == handlerMethodResponseMode) {
			return indeterminationResponseModeExceptionResolve(request, response, handlerMethod, ex);
		}
		switch (handlerMethodResponseMode) {
		case WEB_BODY:
			return webBodyResponseExceptionResolver.resolveException(request, response, handlerMethod, ex);
		case WEB_PAGE:
			return webPageResponseExceptionResolver.resolveException(request, response, handlerMethod, ex);
		}
		return indeterminationResponseModeExceptionResolve(request, response, handlerMethod, ex);
	}

	// ==================================================分模式异常解析==================================================

	/**
	 * 不确定响应模式的异常处理
	 * 
	 * @param request       请求
	 * @param response      响应
	 * @param handlerMethod 处理器方法
	 * @param ex            异常
	 * @return 响应的视图
	 */
	protected ModelAndView indeterminationResponseModeExceptionResolve(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod, Exception ex) {
		throw new UnsupportedOperationException("无法解析的响应模式");
	}

	// ==================================================解析处理器方法响应模式==================================================

	@Nullable
	protected HandlerMethodResponseMode resolveHandlerMethodResponseMode(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod, Exception ex) {
		return handlerMethodResponseModeResolver.resolve(handlerMethod);
	}

}
